<script setup lang="ts">
import { Form } from 'ant-design-vue';
import type { CurrencyBalance, TiKuanFangShiXiangQing } from '~/api/services/main.api';
import { noticeMeta } from '~/composables/useMeta';
import LastTransaction from '../Comps/LastTransaction.vue';
import { filterInputNum, showWithdrawConfirm, toBnInt, toBnVal, toDecimalPlaces, toRateText } from '../ts/utils';

const props = defineProps<{
  currencyInfo?: CurrencyBalance;
  method?: TiKuanFangShiXiangQing;
  isLoadingMethod: boolean;
  bnBalance: ReturnType<typeof bignumber>;
  bnLockedBalance: ReturnType<typeof bignumber>;
  bnAvailableBalance: ReturnType<typeof bignumber>;
}>();

const userStore = useUserStore();

const formData = reactive({
  bank_code: undefined as unknown as string,
  bank_card_name: '',
  bank_card_account: '',
  amount: '',
  bank_ifsc_code: '',
  cpf: '',
  email: '',
  id_type: '',
  id_card: '',
});

const getBankCodeOptionsRef = computed(() => {
  const list = props.method?.banks ?? [];
  return list.map(x => ({ label: x.bank_name, value: x.bank_code, is_default: x.is_default }));
});

watch(getBankCodeOptionsRef, (v) => {
  if (v.length) {
    const def = v.find(x => x.is_default) || v[0];
    formData.bank_code = def?.value ?? '';
  }
}, { immediate: true });

function filterBankCodeOption(input: string, option: any) {
  const _input = input?.toLowerCase?.();
  return option?.value?.toLowerCase?.().includes(_input) || option?.label?.toLowerCase?.().includes(_input);
}

const getIdOptionsRef = computed(() => {
  const list = props.method?.withdraw_id_type ?? [];
  return list.map(x => ({ label: x.type_name, value: x.id_type }));
});

watch(getIdOptionsRef, (v) => {
  if (v.length) {
    formData.id_type = v[0]?.value ?? '';
    formData.id_card = '';
  }
}, { immediate: true });

const getIsPhoneRef = computed(() => !!props.method?.is_phone);

const getIsFscCodeRef = computed(() => !!props.method?.is_ifsc_code);

const getIsCpfRef = computed(() => !!props.method?.is_cpf);

const getIsEmailRef = computed(() => !!props.method?.is_email);

const getCurrencyInfoRef = computed(() => props.currencyInfo);

const getBankCardAccountText = computed(() => {
  const _code = formData.bank_code;
  if (['EVP', 'PIX_EVP'].includes(_code)) {
    return { label: 'EVP', placeholder: $t('23QynmXqAxWcMwqZs10Qo') };
  }
  if (['PHONE', 'PIX_PHONE'].includes(_code)) {
    return { label: $t('qOwMMelgnPiNGweE3jNYl'), placeholder: $t('gwOfiSWaNljicDlBydtH8') };
  }
  if (['EMAIL', 'PIX_EMAIL'].includes(_code)) {
    return { label: $t('wxnfCdf43thnacVZgQa1'), placeholder: $t('zttXb1CiUPpy5BXszb1uP') };
  }
  if (['CPF', 'PIX_CPF'].includes(_code)) {
    return { label: $t('buF7J7YwXxjHsuY9j5N'), placeholder: $t('tHdjRSjkKxtGgsjH0Bzs') };
  }
  if (['CNPJ', 'PIX_CNPJ'].includes(_code)) {
    return { label: $t('iv9PtDpjhZ6OePetoUgk9'), placeholder: $t('wdqtjUisYbFft8hNxSqW') };
  }
  if (getIsPhoneRef.value) {
    return { label: $t('qOwMMelgnPiNGweE3jNYl'), placeholder: $t('gwOfiSWaNljicDlBydtH8') };
  }
  return { label: $t('hetPMwjCTtwMopDKk1X0e'), placeholder: $t('wv9PtikGWvmdDnKsbiaPz') };
});

const getServiceRateRef = computed(() => {
  const rate = toBnVal(props.method?.fee);
  const bnRate = rate?.gt(0) ? rate : bignumber(0);
  const type = props.method?.fee_type;
  return {
    type,
    bnRate,
    text: bnRate.gt(0) && type === 2 ? toRateText(bnRate, false) : '',
  };
});

const getServiceAmountRef = computed(() => {
  const { type, bnRate } = getServiceRateRef.value;
  if (bnRate.gt(0)) {
    const inputVal = toBnVal(formData.amount);
    if (inputVal?.gt(0) && type === 2) {
      return toDecimalPlaces(inputVal.multipliedBy(bnRate));
    }
    return toDecimalPlaces(bnRate);
  }
  return bignumber(0);
});

const getMinMaxRef = computed(() => {
  const bnMin = toBnVal(props.method?.min_withdraw_amount);
  const _min = bnMin ? toDecimalPlaces(bnMin, false, bnMin.decimalPlaces() ?? 2) : bignumber(0);
  const resMin = getServiceRateRef.value.type === 2 ? _min : bignumber.max(getServiceAmountRef.value, _min);
  const bnMax = toBnVal(props.method?.max_withdraw_amount);
  const resMax = bnMax ? toDecimalPlaces(bnMax, false, bnMax.decimalPlaces() ?? 2) : bignumber(0);
  return { min: toBnInt(resMin), max: toBnInt(resMax) };
});

const getMinMaxPlaceholder = computed(() => {
  const { min, max } = getMinMaxRef.value;
  if (min.lte(0) || max.lte(0)) {
    return '';
  }
  return ` (${min.plus(1).toFormat()} ~ ${max.toFormat()})`;
});

const getReceivedAmountRef = computed(() => {
  const inputVal = toBnVal(formData.amount);
  const { min } = getMinMaxRef.value;
  if (!inputVal?.gt(0) || (min.gt(0) && inputVal.lte(min))) {
    return bignumber(0);
  }
  const result = toDecimalPlaces(inputVal.minus(getServiceAmountRef.value));
  return result.gt(0) ? result : bignumber(0);
});

const amountValidateInfo = reactive({ isError: false, text: '' });

function setAmountValidateInfo(isError = false, text = '') {
  amountValidateInfo.isError = isError;
  amountValidateInfo.text = isError ? text : '';
  return formResult();
}

const $form = Form.useForm(formData, reactive({
  amount: [
    {
      validator(_: any, val: string) {
        const inputVal = toBnVal(val);

        if (!inputVal || inputVal?.lte(0))
          return setAmountValidateInfo(true, $t('hWstS1hvXUnYtJxNPnio'));

        if (!inputVal.isInteger())
          return setAmountValidateInfo(true, $t('5Jzfj3NvqPzFh04Mu8qmR'));

        if (inputVal.gt(props.bnAvailableBalance) || props.bnAvailableBalance.lte(0))
          return setAmountValidateInfo(true, $t('oGiAq6Hya7nrnOzZfduQr'));

        const { min, max } = getMinMaxRef.value;

        if (max.gt(0) && inputVal.gt(max))
          return setAmountValidateInfo(true, $t('mkMBakhFtLGpRt9cRBaD7', { amount: max.toFormat() }));

        if (min.gt(0) && inputVal.lte(min))
          return setAmountValidateInfo(true, $t('lsLjWbuZu4iu9sNSfrG4', { amount: min.toFormat() }));

        return setAmountValidateInfo();
      },
    },
  ],
  bank_card_name: [
    {
      validator(_: any, value: string) {
        if (!getIsPhoneRef.value && !value)
          return formResult($t('sofSLy2W5gtkQLou4yoLn'));

        return formResult();
      },
    },
  ],
  bank_code: [
    {
      validator(_: any, value: string) {
        if (getBankCodeOptionsRef.value.length > 0 && !value)
          return formResult($t('5UlRpoHeehGPj17ntpLg'));

        return formResult();
      },
    },
  ],
  bank_card_account: [
    {
      validator(_: any, value: string) {
        return value ? formResult() : formResult(getBankCardAccountText.value.placeholder);
      },
    },
  ],
  bank_ifsc_code: [
    {
      validator(_: any, value: string) {
        if (getIsFscCodeRef.value && !value)
          return formResult($t('2GrLFFeBz8h1XLzorTtW'));

        return formResult();
      },
    },
  ],
  cpf: [
    {
      validator(_: any, value: string) {
        if (getIsCpfRef.value && !value)
          return formResult($t('tM7YMhZnMxeD6ArO57q'));

        return formResult();
      },
    },
  ],
  email: [
    {
      validator(_: any, value: string) {
        if (getIsEmailRef.value && !value)
          return formResult($t('aw95tLwTkGmrgSVCHW'));

        return formResult();
      },
    },
  ],
  id_type: [
    {
      validator(_: any, value: string) {
        if (getIdOptionsRef.value.length > 0 && !value)
          return formResult($t('ys8KjMzsbXuw7rk_7j6Y'));

        return formResult();
      },
    },
  ],
  id_card: [
    {
      validator(_: any, value: string) {
        if (getIdOptionsRef.value.length > 0 && !value)
          return formResult($t('e4ASh7t0Sr1YsJ70AyDbw'));

        return formResult();
      },
    },
  ],
}));

const getAmountItemsRef = computed(() => {
  const pmax = toBnInt(props.bnAvailableBalance);
  const pmaxVal = pmax.gt(0) ? pmax : bignumber(0);
  const { min: cmin, max: cmax } = getMinMaxRef.value;
  const max = pmaxVal.gt(cmax) ? cmax : pmaxVal;
  return [
    { key: 'Min', value: cmin.gt(max) || pmax.lte(0) ? '0' : cmin.plus(1).toString() },
    { key: '25%', value: toBnInt(pmaxVal.multipliedBy(0.25)).toString() },
    { key: '50%', value: toBnInt(pmaxVal.multipliedBy(0.5)).toString() },
    { key: 'Max', value: max.toString() },
  ];
});

function selectAmountItem(val: string) {
  const bnVal = toBnInt(bignumber(val));
  formData.amount = bnVal.isNaN() || bnVal.lte(0) ? '0' : bnVal.toString();
}

async function inputAmount(e: any) {
  await nextTick();
  formData.amount = filterInputNum(e.target?.value, 'int', 0);
}

function clearValidate() {
  $form.clearValidate();
  setAmountValidateInfo();
}

const withdrawFaitMut = useMutation({
  mutationKey: [apis.apiFundWithdrawFaitSubmit.id],
  mutationFn: apis.apiFundWithdrawFaitSubmit.setDefaultConfig({ successMessage: false, errorMessage: true }),
  onSuccess: (resp) => {
    useCurrencyStore().balanceQry.refetch();
    noticeMeta().withdraw({ currency: resp.currency.currency, id: resp.address });
    antdModal.success({
      content: $t('raiIdB_7L3v3oTkkGnGbO'),
      class: 'ant-cover__confirm-modal',
      okCancel: false,
      centered: true,
    });
    globalPopups.wallet.close();
    $form.resetFields();
    clearValidate();
  },
});

const btnLoading = computed(() => withdrawFaitMut.isPending.value);

async function handleSubmit() {
  if (await $form.validate().catch(() => false)) {
    const res = userStore.verified?.authenticator ? await openAuthFlowPopup('verify2FA').catch(() => undefined) : {};
    showWithdrawConfirm(() => {
      withdrawFaitMut.mutate({ requestBody: {
        ...formData,
        ...res,
        amount: toBnInt(bignumber(formData.amount)).toString(),
        bank_card_name: (getIsPhoneRef.value ? formData.bank_card_account : formData.bank_card_name) ?? '',
        bank_code: (getBankCodeOptionsRef.value.length ? formData.bank_code : props.method?.bank_code) ?? '',
        code: props.method?.code ?? '',
        currency: getCurrencyInfoRef.value?.currency ?? '',
        bank_ifsc_code: getIsFscCodeRef.value ? formData.bank_ifsc_code : '',
        cpf: getIsCpfRef.value ? formData.cpf : '',
        email: getIsEmailRef.value ? formData.email : void 0,
        id_type: getIdOptionsRef.value.length ? formData.id_type : void 0,
        id_card: getIdOptionsRef.value.length ? formData.id_card : void 0,
      } });
    }, props.bnBalance, props.bnLockedBalance);
  }
}
</script>

<template>
  <div class="relative flex flex-1 flex-col justify-between text-sm text-sys-text-body lt-mobile:h-full">
    <div class="lt-mobile:(flex flex-1 flex-col overflow-y-auto)">
      <AForm @keypress.enter="handleSubmit">
        <AFormItem class="!mb-3">
          <slot />
        </AFormItem>

        <div v-if="!!method">
          <AFormItem v-if="!getIsPhoneRef && !isLoadingMethod" v-bind="$form.validateInfos.bank_card_name" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              {{ $t('rfIbEfnX97O_1stKmtlLh') }}
            </div>
            <AInput
              v-model:value="formData.bank_card_name"
              allowClear
              :placeholder="$t('sofSLy2W5gtkQLou4yoLn')"
            />
          </AFormItem>

          <AFormItem v-if="getBankCodeOptionsRef.length && !isLoadingMethod" v-bind="$form.validateInfos.bank_code" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              {{ method?.is_account_type ? $t('cIiO5q80uU8Y0tgmrlJ8') : $t('n04tTDh_3bQxof7jzqVb') }}
            </div>
            <ASelect
              v-model:value="formData.bank_code"
              :placeholder="$t('5UlRpoHeehGPj17ntpLg')"
              :dropdownMatchSelectWidth="false"
              :listHeight="300"
              :options="getBankCodeOptionsRef"
              showSearch
              :filterOption="filterBankCodeOption"
              @change="clearValidate()"
            >
              <template #option="{ label }">
                <div class="max-w-90 truncate lt-mobile:max-w-[86vw]">
                  {{ label }}
                </div>
              </template>
            </ASelect>
          </AFormItem>

          <AFormItem v-if="getIsEmailRef" v-bind="$form.validateInfos.email" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              {{ $t('wxnfCdf43thnacVZgQa1') }}
            </div>
            <AInput
              v-model:value="formData.email"
              allowClear
              :placeholder="$t('hVaEobWzd70kjGP9Awnt')"
            />
          </AFormItem>

          <AFormItem v-bind="$form.validateInfos.bank_card_account" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              {{ getBankCardAccountText.label }}
            </div>
            <AInput v-model:value="formData.bank_card_account" :placeholder="getBankCardAccountText.placeholder" allowClear />
          </AFormItem>

          <template v-if="getIdOptionsRef.length && !isLoadingMethod">
            <AFormItem v-bind="$form.validateInfos.id_type" class="!mb-3">
              <div class="mb-1.5 text-sm text-sys-text-body">
                {{ $t('g9HbAnRYzXwmbDbvpfS') }}
              </div>
              <ASelect
                v-model:value="formData.id_type"
                :placeholder="$t('ys8KjMzsbXuw7rk_7j6Y')"
                :dropdownMatchSelectWidth="false"
                :listHeight="300"
                :options="getIdOptionsRef"
              >
                <template #option="{ label }">
                  <div class="max-w-90 truncate lt-mobile:max-w-[86vw]">
                    {{ label }}
                  </div>
                </template>
              </ASelect>
            </AFormItem>

            <AFormItem v-bind="$form.validateInfos.id_card" class="!mb-3">
              <div class="mb-1.5 text-sm text-sys-text-body">
                {{ $t('l11eEcrFp9J4t7blHfGv') }}
              </div>
              <AInput
                v-model:value="formData.id_card"
                allowClear
                :placeholder="$t('e4ASh7t0Sr1YsJ70AyDbw')"
              />
            </AFormItem>
          </template>

          <AFormItem v-if="getIsFscCodeRef" v-bind="$form.validateInfos.bank_ifsc_code" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              ifsc code
            </div>
            <AInput
              v-model:value="formData.bank_ifsc_code"
              allowClear
              :placeholder="$t('2GrLFFeBz8h1XLzorTtW')"
            />
          </AFormItem>

          <AFormItem v-if="getIsCpfRef" v-bind="$form.validateInfos.cpf" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              cpf
            </div>
            <AInput
              v-model:value="formData.cpf"
              allowClear
              :placeholder="$t('tM7YMhZnMxeD6ArO57q')"
            />
          </AFormItem>

          <AFormItem v-bind="$form.validateInfos.amount" class="!mb-3" :validateStatus="amountValidateInfo.isError ? 'error' : 'success'">
            <div class="mb-1.5 flex-between items-end whitespace-normal break-words break-all text-sm text-sys-text-body">
              <div>{{ $t('m8mu3JTsq0mNmDfh2GDh1') }}{{ getMinMaxPlaceholder }}</div>
              <div class="whitespace-normal break-words break-all text-xs">
                {{ $t('fzQWzNp8QafNxHzEvAu3F') }}：{{ toBnInt(bnAvailableBalance).toFormat() }}
              </div>
            </div>
            <AInput
              v-model:value="formData.amount"
              class="w-full"
              allowClear
              :placeholder="`${$t('qlxJcfsbDcKdovNZpjeKl')}${getMinMaxPlaceholder}`"
              inputmode="numeric"
              :maxlength="18"
              @change="inputAmount"
              @blur="inputAmount"
            />
            <template #help>
              <div class="grid grid-cols-[1fr_auto] mb-2 w-full gap-4">
                <span class="text-sm text-[#dc4446]">{{ amountValidateInfo.isError ? amountValidateInfo.text : '' }}</span>
                <slot name="lockedBalance" />
              </div>
            </template>
          </AFormItem>

          <AFormItem class="!mb-0">
            <div class="grid grid-cols-4 mb-3 mb-3 mt-2 gap-2">
              <div
                v-for="item of getAmountItemsRef"
                :key="item.key"
                class="min-h-9 w-full flex cursor-pointer items-center justify-center rounded-lg bg-sys-layer-d text-sys-text-head"
                :class="{ '!bg-sys-layer-e': formData.amount && item.value === formData.amount }"
                @click="selectAmountItem(item.value)"
              >
                {{ item.key }}
              </div>
            </div>
          </AFormItem>

          <AFormItem v-if="getServiceAmountRef.gt(0) && getReceivedAmountRef.gt(0)" class="!mb-3">
            <div class="mb-1.5 text-sm text-sys-text-body">
              {{ $t('np4skhNFeYpCk9AepQq') }}
            </div>
            <div class="grid grid-cols-[auto_1fr] items-center gap-x-2 border-(1px sys-layer-e solid) rounded-lg bg-sys-layer-d px-2.5 py-1.5">
              <div class="text-xs">
                {{ $t('txnBsvvLm0IcSoZ0lYusm') }}
              </div>
              <div class="whitespace-normal break-words break-all text-right text-xl text-green font-semibold">
                {{ getReceivedAmountRef.toFormat() }}
              </div>
              <div class="text-xs">
                {{ $t('mnzMeff8rTooSapjfgwIr') }} {{ getServiceRateRef.text }}
              </div>
              <div class="whitespace-normal break-words break-all text-right">
                {{ `${getServiceAmountRef.toFormat()} ${getCurrencyInfoRef?.currency}` }}
              </div>
            </div>
          </AFormItem>
        </div>
      </AForm>

      <LastTransaction :class="{ '!hidden': !method }" type="withdraw" />
    </div>

    <div v-if="!!method" class="pt-3 lt-mobile:(mb-3 mt-auto)">
      <AButton
        class="ant-cover__Button-3d-primary w-full"
        type="primary"
        :loading="btnLoading"
        :disabled="btnLoading"
        @click="handleSubmit"
      >
        {{ $t('xQp2HJedTncmCsXifzn3') }}
      </AButton>
    </div>
  </div>
</template>
